package HMM;

import TrainingData.TrainingInstance;
import TrainingData.TrainingInstanceCollection;


/**
 * @author Gergely Neu
 *
 * Simple perceptron training of an HMM.
 */
public class Perceptron extends TrainingMethod {
	
	/**
	 * Constructor for Perceptron. This method does not have any parameters other than the general ones.
	 * 
	 * @param iterNr number of iterations to carry out.
	 * @param trainingData the data used for training. 
	 * @param testData the data used for testing.
	 */
	public Perceptron(int iterNr, TrainingInstanceCollection trainingData,TrainingInstanceCollection testData){
		super(iterNr,trainingData,testData);
	
	}
	

	@Override
	protected Updates iterationStep(DoubleSparseMatrix transitionMx, DoubleSparseMatrix emissionMx) {
		
		int numStates = transitionMx.getColNr();
		int numEmissions = emissionMx.getColNr();
		
		DoubleSparseMatrix deltaTransMx = new DoubleSparseMatrix(numStates,numStates, 0);
		DoubleSparseMatrix deltaEmissMx = new DoubleSparseMatrix(numStates,numEmissions, 0);
		
		int inst =0;
		
		for (TrainingInstance instance : _trainingData) {
			
			if ((inst++%100)==0 && false)
				System.out.println("[Training sentence "+ (inst-1) + "]");
			
			int[] emissions = instance.getEmissions();
			int[] states = instance.getStates();
			
			int L = emissions.length;
			
			HMMCommonFunctions.computeViterbiScores(emissions, emissionMx, transitionMx);
			
			int[] decodedStateArray = HMMCommonFunctions.decodeFrom(emissions, L, 0);
			
			for (int i = 1; i < L; i++) { 
				deltaTransMx.increment(decodedStateArray[i-1], decodedStateArray[i], -1);
				
				deltaEmissMx.increment(decodedStateArray[i],emissions[i], -1);
				
				deltaTransMx.increment(states[i-1],states[i], 1);
				
				deltaEmissMx.increment(states[i],emissions[i], 1);
			}
			
			deltaEmissMx.increment(decodedStateArray[0],emissions[0], -1);
			
			deltaEmissMx.increment(states[0],emissions[0], 1);
			
		}
		
		return new Updates(deltaTransMx, deltaEmissMx);
	}

}
